package utils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * Classe usada para extrair dados de um arquivo xml
 * 
 */

public class Extrator {
	
	private String arquivoXML;
	private Document documentoXML;

	public Extrator() {
		arquivoXML = null;
		documentoXML = null;
	}
	
	public Extrator(String aArquivoXML) throws ParserConfigurationException, SAXException, IOException{
		arquivoXML = aArquivoXML;
		parseXML();
	}
	
	/** Abre o arquivo xml */
	private void parseXML() throws ParserConfigurationException, SAXException, IOException{
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		documentoXML = db.parse(new File(arquivoXML));
	}
	
	/** Lista todo o documento xml */
	public void listarXML(){
		percorrerXML(elementoRoot());
	}
	
	/** Retorna um objeto "Element" que contém todo o xml */
	public Element elementoRoot(){
		return documentoXML.getDocumentElement();
	}
	
	/** Percorre e impreme todos os dados do arquivo xml */
	private void percorrerXML(Element element){
		NodeList lista = element.getChildNodes();
		
		for(int i = 0; i < lista.getLength(); i++){
			Node noLocal = lista.item(i);
			if(noLocal.getNodeType() == Node.ELEMENT_NODE && noLocal.getNodeType() != Node.TEXT_NODE){
				System.out.printf("%s", noLocal.getNodeName().toUpperCase());
				if(noLocal.hasAttributes()){
					for(int j = 0; j < noLocal.getAttributes().getLength(); j++){
						System.out.printf("\n\t%s: %s",
								noLocal.getAttributes().item(j).getNodeName().toUpperCase(), noLocal.getAttributes().item(j).getNodeValue());
					}
					System.out.printf("\n");
				}
				percorrerXML((Element) noLocal);
			}
			else if(noLocal.getNodeType() == Node.TEXT_NODE){
				if ((noLocal.getNodeValue() != null) && !(noLocal.getNodeValue().trim().equals("")))
					System.out.printf(": %s\n", noLocal.getNodeValue());
			}
		}		
	}
	
	/** Percorre e retorna todos os dados do arquivo xml */
    public ArrayList<String> percorrerERetornarXML(Element element){
    	NodeList lista = element.getChildNodes();
    	ArrayList<String> operations = new ArrayList<String>();
    	for(int i = 0; i < lista.getLength(); i++){
            Node noLocal = lista.item(i);
            if(noLocal.getNodeType() == Node.ELEMENT_NODE && noLocal.getNodeType() != Node.TEXT_NODE){
            	if(noLocal.hasAttributes()){
            		for(int j = 0; j < noLocal.getAttributes().getLength(); j++){
            			if(noLocal.getAttributes().item(j).getNodeName() == "name")
            				operations.add(noLocal.getAttributes().item(j).getNodeValue());
                    }
                    operations.add("\n");
                }
                percorrerXML((Element) noLocal);
            }
    	}
    	return operations;
    }
	
	/** Busca um nó por nome, e retorna o mesmo como "Node" */
	public Node buscarTagPorNome(String nome){
		NodeList lista = elementoRoot().getElementsByTagName(nome);
		Node no = null;
		for(int i = 0; i < lista.getLength(); i++){
			if(lista.item(i).getNodeName().equals(nome))
				no = lista.item(i);
		}
		return no;
	}
	
	/** Impreme todo os dados do xml */
	public void listarDadosPorNome(String nome){
		Element element = (Element) elementoRoot().getElementsByTagName(nome).item(0);
		percorrerXML(element);	
	}
	
	 /** Retorna os dados do nó desejado em forma de ArrayList */
    public ArrayList<String> retornarDadosPorNome(String nome){
    	Element element = (Element) elementoRoot().getElementsByTagName(nome).item(0);
    	return percorrerERetornarXML(element);  
    }

	public String getArquivoXML() {
		return arquivoXML;
	}

	public void setArquivoXML(String arquivoXML) {
		this.arquivoXML = arquivoXML;
		try {
			parseXML();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
